package m.system.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import m.common.action.*;
import m.system.exception.MException;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;

public class ActionUtil {
	private static final Map<String, RequestParam> paramMap=new HashMap<>();
	private static final Set<String> formDataMap=new HashSet<>();

	/**
	 * 初始化Action方法
	 */
	public static void init(ActionRequest meta,Class<? extends Action> actionClass){
		Method[] ms=ClassUtil.getDeclaredMethods(actionClass);
		for(Method m : ms) {
			RequestMethod rm=m.getAnnotation(RequestMethod.class);
			if(null==rm) continue;
			RequestParam map= new RequestParam();
			map.setTransaction(rm.transaction());
			map.setMethod(m.getName());
			map.setAction(actionClass);
			for(Parameter p :m.getParameters()){
				Param rp=p.getAnnotation(Param.class);
				if(null!=rp)
					map.getParamList().put(rp.value(),p.getType());
				else
					map.getParamList().put(p.getName(),null);
			}
			String urlPath=("/"+meta.name()+"/"+(StringUtil.isSpace(rm.name())?m.getName():rm.name())).replaceAll("//","/");
			paramMap.put(urlPath, map);
			if(rm.isFormData()){
				formDataMap.add(urlPath);
			}
		}
	}
	/**
	 * 获取action请求注解对应方法的参数
	 */
	public static RequestParam getRequestParamList(String urlPath) {
		return paramMap.get(urlPath);
	}

	/**
	 * 是否multipart/form-data请求
	 */
	public static boolean isFormData(String urlPath){
		return formDataMap.contains(urlPath);
	}

	/**
	 * 把putData合并到data里
	 *  data
	 *  putData
	 */
	public static void fillJSONObject(JSONObject data,JSONObject putData) {
		for(String key : putData.keySet()) {
			Object dd=data.get(key);
			if(dd instanceof JSONObject) {
				fillJSONObject((JSONObject)dd, putData.getJSONObject(key));
			}else if(dd instanceof JSONArray) {
				((JSONArray)dd).addAll(putData.getJSONArray(key));
			}else {
				data.put(key, putData.get(key));
			}
		}
	}
	public static void fillJSONObject(JSONObject data, String name, Object value) {
		boolean flag=true;
		int index=0;
		String[] arr=name.split("");
		for(int i=0;i<arr.length;i++){
			if(arr[i].equals("[")) flag=false;
			else if(arr[i].equals("]")) flag=true;
			if(flag&&arr[i].equals(".")){
				index=i;
				break;
			}
		}
		if(index>0){
			String f1=name.substring(0,index);
			String f2=name.substring(f1.length()+1);
			if(f1.contains("[") &&f1.indexOf("]")==f1.length()-1){
				String nm=f1.substring(0,f1.indexOf("["));
				String ni=f1.substring(nm.length()+1,f1.length()-1);
				if(!ni.matches("[0-9]*")){
                    data.computeIfAbsent(nm, k -> new JSONObject());
					fillJSONObject((JSONObject)data.get(nm),ni+"."+f2,value);
				}else{
                    data.computeIfAbsent(nm, k -> new JSONArray());
					int n=Integer.parseInt(ni);
					JSONArray ls=(JSONArray)data.get(nm);
					for(int i=1;i<=n+1;i++){
						if(ls.size()<i) ls.add(new JSONObject());
					}
					fillJSONObject((JSONObject)ls.get(n),f2,value);
				}
			}else{
                data.computeIfAbsent(f1, k -> new JSONObject());
				fillJSONObject((JSONObject)data.get(f1),f2,value);
			}
		}else{
			if(name.contains("[") && name.indexOf("]")== name.length()-1){
				String nm= name.substring(0, name.indexOf("["));
				String ni= name.substring(nm.length()+1, name.length()-1);
				SystemUtil.println(nm+"--"+ni);
				if(!ni.matches("[0-9]*")){
                    data.computeIfAbsent(nm, k -> new JSONObject());
					((JSONObject)data.get(nm)).put(ni, value);
				}else{
                    data.computeIfAbsent(nm, k -> new JSONArray());
					JSONArray list = (JSONArray)data.get(nm);
					if(StringUtil.isSpace(ni)) {
						String[] strs=value.toString().split(",");
						list.addAll(Arrays.asList(strs));
					}else {
						int n=Integer.parseInt(ni);
						for(int i=0;i<=n+1;i++){
							if(list.size()<i) list.add(null);
						}
						list.set(n, value);
					}
				}
			}else{
				data.put(name, value);
			}
		}
	}

	public static Object getInAttribute(Object action,String paramName) throws MException{
		String[] paramNames=paramName.split("\\.");
		if(paramNames.length>1){
			Object obj=ClassUtil.getFieldValue(action, paramNames[0]);
			if(null!=obj){
				return getInAttribute(obj, paramName.substring(paramName.indexOf(".")+1));
			}else{
				return null;
			}
		}else{
			return ClassUtil.getFieldValue(action, paramName);
		}
	}

}
